package com.zzyl.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.BCrypt;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.base.ResponseResult;
import com.zzyl.constant.CacheConstant;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.LoginDto;
import com.zzyl.dto.UserDto;
import com.zzyl.entity.User;
import com.zzyl.entity.UserRole;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.mapper.UserMapper;
import com.zzyl.mapper.UserRoleMapper;
import com.zzyl.properties.JwtTokenManagerProperties;
import com.zzyl.properties.SecurityConfigProperties;
import com.zzyl.service.UserService;
import com.zzyl.utils.JwtUtil;
import com.zzyl.utils.NoProcessing;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.vo.UserRoleVo;
import com.zzyl.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private JwtTokenManagerProperties jwtTokenManagerProperties;

    @Autowired
    private ResourceMapper resourceMapper;

    @Autowired
    private SecurityConfigProperties securityConfigProperties;

    @Autowired
    private RedisTemplate<String,String>  redisTemplate                                                        ;

    @Override
    public PageResponse<UserVo> getByPage1(UserDto userDto, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        String deptNo = userDto.getDeptNo();
        userDto.setDeptNo(NoProcessing.processString(deptNo));
        //分页查询用户信息
        Page<UserVo> page = userMapper.getByPage1(userDto);
        //查询所有的用户角色关联信息
        List<UserRoleVo> all = userRoleMapper.getAllAndName();
        //循环匹配
        for (UserVo userVo : page) {
            Long id = userVo.getId();
            HashSet<String> roleVoIds = new HashSet<>();
            HashSet<String> roleLabels = new HashSet<>();
            for (UserRoleVo userRoleVo : all) {
                if ((userRoleVo.getUserId() + "").equals(id + "")) {
                    roleVoIds.add(userRoleVo.getRoleId() + "");
                    roleLabels.add(userRoleVo.getRoleName());
                }
            }
            userVo.setRoleVoIds(roleVoIds);
            userVo.setRoleLabels(roleLabels);
        }
        return PageResponse.of(page, UserVo.class);
    }

    @Override
    @Transactional
    public void add(UserDto userDto) {
        User user = BeanUtil.toBean(userDto, User.class);
        String password = "888itcast.CN764%...";
        user.setPassword(BCrypt.hashpw(password, BCrypt.gensalt()));
        userMapper.insert(user);
        Set<String> roleVoIds = userDto.getRoleVoIds();
        for (String roleVoId : roleVoIds) {
            UserRole userRole = UserRole.builder()
                    .userId(user.getId())
                    .dataState(userDto.getDataState())
                    .roleId(Long.valueOf(roleVoId))
                    .build();
            userRoleMapper.insert(userRole);
        }
    }

    @Override
    @Transactional
    public UserVo update(UserDto userDto) {

        User user = BeanUtil.toBean(userDto, User.class);
        userMapper.updateByPrimaryKeySelective(user);
        Long id = userDto.getId();
        Set<String> roleVoIds = userDto.getRoleVoIds();
        userRoleMapper.deleteByUserId(id);
        for (String roleVoId : roleVoIds) {
            UserRole userRole = UserRole.builder()
                    .userId(user.getId())
                    .dataState(userDto.getDataState())
                    .roleId(Long.valueOf(roleVoId))
                    .build();
            userRoleMapper.insert(userRole);
        }
        return null;
    }

    @Override
    public void updateStatus(Long id, String status) {

        userMapper.updateStatus(id,status);

    }

    @Override
    public void delete(Long userId) {
        userMapper.updateIsDelete(userId);

    }

    @Override
    public void resetPw(Long userId) {
        String password = "888itcast.CN764%...";
        String newPw = BCrypt.hashpw(password, BCrypt.gensalt());

        userMapper.resetPw(userId,newPw);
    }

    @Override
    public UserVo userList(UserDto userDto) {
        User user=userMapper.userList(userDto);
        return BeanUtil.toBean(user,UserVo.class);

    }

    @Override
    public PageResponse<UserVo> getByPage(UserDto userDto, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        String deptNo = userDto.getDeptNo();
        userDto.setDeptNo(NoProcessing.processString(deptNo));
        PageResponse<UserVo> page=userMapper.getByPage(userDto);
        return PageResponse.of(page, UserVo.class);
    }

    @Override
    public UserVo login(LoginDto loginDto) {
        //根据用户名查询用户
        User user=userMapper.selectByUserName(loginDto.getUsername());
        //判断用户是否存在
        if(ObjectUtil.isEmpty(user)){
            throw new BaseException(BasicEnum.LOGIN_FAIL);
        }
        //判断用户状态
        if(SuperConstant.DATA_STATE_1.equals(user.getDataState())){
            throw new BaseException(BasicEnum.ACCOUNT_DISABLED);
        }
        if(!BCrypt.checkpw(loginDto.getPassword(),user.getPassword())){
            throw new BaseException(BasicEnum.INCORRECT_PASSWOED);
        }
        //密码脱敏
        user.setPassword("");
        UserVo userVo = BeanUtil.toBean(user, UserVo.class);

        //根据用户查询 按钮资源
        List<String> resourceList= resourceMapper.selectListByUserId(user.getId());

        //获取白名单 列表
        List<String> publicAccessUrls = securityConfigProperties.getPublicAccessUrls();
        resourceList.addAll(publicAccessUrls);
        //把合并的数据储存到redis
        String key = CacheConstant.PUBLIC_ACCESS_URLS + user.getId();
        Integer ttl = jwtTokenManagerProperties.getTtl();
        redisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(resourceList),ttl/1000, TimeUnit.SECONDS);

        //设置共享数据
        HashMap<String, Object> claim = new HashMap<>();
        claim.put("currentUser", JSONUtil.toJsonStr(userVo));
        //生成令牌 token
        String token = JwtUtil.createJWT(jwtTokenManagerProperties.getBase64EncodedSecretKey(),
                jwtTokenManagerProperties.getTtl(), claim);
        //封装vo对象
        userVo.setUserToken(token);
        return userVo;
    }

}